#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import json
import random
from collections import OrderedDict

import AIManage
import WeightAI

KEY_MESSAGE_TYPE = "messageType"
KEY_ROOM_ID = "roomID"
KEY_PLAYER_INDEX = "playerIndex"
KEY_PLAYER_NAME = "playerName"
KEY_PLAYER_ICON = "playerIcon"
KEY_PLAYER_COUNT = "playerCount"
KEY_READY_PLAYERS = "readyPlayers"

RANDOM_ROOM_NUM = -1
START_ROOM_COUNT = 5
START_AI_COUNT = 9

class MessageType:
    MESSAGE_ROOM_JOIN = "room_join"
    MESSAGE_ROOM_CREATE = "room_create"
    MESSAGE_ROOM_EXIT = "room_exit"
    MESSAGE_ROOM_RETURN = "room_return"
    MESSAGE_ROOM_KICKOUT = "room_kick_out"
    ERROR_NO_ROOM = "error_no_room"
    ERROR_PAUSE = "error_pause"

class RoomManage:
    def __init__(self):
        self.m_dicRoomPlayers = {}
        self.m_rgWaittingRoom = []
        self.m_rgCnnectingPlayers = []

    def getRoomMessageType(self, strMessage):
        dicJsonMessage = json.loads(strMessage)
        strMessageType = dicJsonMessage[KEY_MESSAGE_TYPE]
        
        return strMessageType

    def checkIsRoomMessage(self, strMessage):
        try:
            dicJsonMessage = json.loads(strMessage)
            if dicJsonMessage.has_key(KEY_MESSAGE_TYPE):
                strMessageType = dicJsonMessage[KEY_MESSAGE_TYPE]
                if strMessageType == MessageType.MESSAGE_ROOM_JOIN or strMessageType == MessageType.MESSAGE_ROOM_CREATE or strMessageType == MessageType.MESSAGE_ROOM_EXIT or strMessageType == MessageType.MESSAGE_ROOM_RETURN or strMessageType == MessageType.MESSAGE_ROOM_KICKOUT:
                    return True
                else:
                    return False
            else:
                return False
    
        except ValueError:
            print "strMessage is not json"
            return False
        
        except Exception,e:
            print 'error:',e
            return False


    def createRoom(self, strMessage, player):
        try:
            nRoomID = random.randint(1,9) * 1000 + random.randint(0,999)
            i = 0
            while i < 10000 and self.m_dicRoomPlayers.has_key(nRoomID):
                nRoomID = random.randint(1,9) * 1000 + random.randint(0,999)
                i += 1
        
            dicJsonMessage = json.loads(strMessage)
            nPlayerCount = dicJsonMessage[KEY_PLAYER_COUNT]
            strPlayerName = dicJsonMessage[KEY_PLAYER_NAME]
            nPlayerIcon = dicJsonMessage[KEY_PLAYER_ICON]
            rgPlayers = []
            rgPlayers.append(nPlayerCount)
            rgPlayers.append(player)
            self.m_dicRoomPlayers[nRoomID] = rgPlayers
            print "Player %s create RoomID %d" % (player.m_strPlayerName, nRoomID)

            return (nRoomID, nPlayerCount, strPlayerName, nPlayerIcon, self.__createRoomMessage(nRoomID, nPlayerCount))
    
        except Exception,e:
            print 'error:',e
            return (0, 0, "")

    def joinRoom(self, strMessage, player):
        try:
            dicJsonMessage = json.loads(strMessage)
            nRoomID = dicJsonMessage[KEY_ROOM_ID]
            strPlayerName = dicJsonMessage[KEY_PLAYER_NAME]
            nPlayerIcon = dicJsonMessage[KEY_PLAYER_ICON]
            
            player.m_strPlayerName = strPlayerName
            
            print "player %s try to join room %d" % (player.m_strPlayerName, nRoomID)
            
            rgPlayers = []
            if nRoomID == RANDOM_ROOM_NUM:
                if len(self.m_rgWaittingRoom) > 0:
                    nRoomID = self.m_rgWaittingRoom[0]
                    rgPlayers = self.m_dicRoomPlayers[nRoomID]
                    nPlayerCount = rgPlayers[0]
                    rgPlayers.append(player)
                    
                    if nPlayerCount + 1 == len(rgPlayers):
                        self.roomIsFull(nRoomID)
                else:
                    nRoomID = random.randint(1,9) * 1000 + random.randint(0,999)
                    i = 0
                    while i < 10000 and self.m_dicRoomPlayers.has_key(nRoomID):
                        nRoomID = random.randint(1,9) * 1000 + random.randint(0,999)
                        i += 1
                    
                    nPlayerCount = random.randint(3,5)
                    rgPlayers = []
                    rgPlayers.append(nPlayerCount)
                    rgPlayers.append(player)
                    self.m_dicRoomPlayers[nRoomID] = rgPlayers
                    
            else:
                if self.m_dicRoomPlayers.has_key(nRoomID) == False:
                    return (-1, -1, -1, -1, -1, self.__noRoomMessage())
            
                rgPlayers = self.m_dicRoomPlayers[nRoomID]
                rgPlayers.append(player)
                nPlayerCount = rgPlayers[0]
            
            nCurrentPlayerCount = len(rgPlayers) - 1
            nPlayerIndex = nCurrentPlayerCount - 1
            
            return (nRoomID, nPlayerCount, nCurrentPlayerCount, strPlayerName, nPlayerIcon, self.__joinRoomMessage(nRoomID, nPlayerIndex, nPlayerCount, rgPlayers))
        except Exception,e:
            print 'error:',e
            return (0, 0, 0, "")

    def roomIsFull(self, nRoomID):
        try:
            self.m_rgWaittingRoom.remove(nRoomID)
            print "Room %d is Full" % nRoomID
        except Exception,e:
            print 'error:',e

    def disposePlayerRoom(self, nRoomID, player, bDisConnect):
        if nRoomID != 0 :
            try:
                self.m_rgWaittingRoom.remove(nRoomID)
            except Exception,e:
                print 'wattingRoom has no room ',nRoomID
    
        if (self.m_dicRoomPlayers.has_key(nRoomID)):
            self.m_dicRoomPlayers[nRoomID].remove(player)
            del self.m_dicRoomPlayers[nRoomID]

        if bDisConnect:
            try:
                self.m_rgCnnectingPlayers.remove(player)
            except Exception,e:
                print 'cnnectingPlayers has no player ',player

    def getPlayers(self, nRoomID):
        rgPlayers = []
        try:
            i = 1
            while i < len(self.m_dicRoomPlayers[nRoomID]):
                rgPlayers.append(self.m_dicRoomPlayers[nRoomID][i])
                i += 1
        except Exception,e:
            print e
        return rgPlayers

    def __createRoomMessage(self, nRoomID, nPlayerCount):
        dicCreateRoomMessage = OrderedDict()
        dicCreateRoomMessage[KEY_MESSAGE_TYPE] = MessageType.MESSAGE_ROOM_CREATE
        dicCreateRoomMessage[KEY_ROOM_ID] = nRoomID
        dicCreateRoomMessage[KEY_PLAYER_INDEX] = 0
        dicCreateRoomMessage[KEY_PLAYER_COUNT] = nPlayerCount

        strJsonMessage = json.dumps(dicCreateRoomMessage)
        return strJsonMessage

    def __joinRoomMessage(self, nRoomID, nPlayerIndex, nPlayerCount, rgPlayers):
        try:

            dicJoinRoomMessage = OrderedDict()
            dicJoinRoomMessage[KEY_MESSAGE_TYPE] = MessageType.MESSAGE_ROOM_JOIN
            dicJoinRoomMessage[KEY_ROOM_ID] = nRoomID
            dicJoinRoomMessage[KEY_PLAYER_INDEX] = nPlayerIndex
            dicJoinRoomMessage[KEY_PLAYER_COUNT] = nPlayerCount
        
            rgPlayerNames = []
            i = 1
            while i < len(rgPlayers):
                rgPlayerNames.append(rgPlayers[i].m_strPlayerName)
                i += 1
            dicJoinRoomMessage[KEY_READY_PLAYERS] = rgPlayerNames
            
            strJsonMessage = json.dumps(dicJoinRoomMessage)
            print " Jonin room message : ", strJsonMessage
            return strJsonMessage
    
        except Exception,e:
            print "error : ", e
            return ""

    def __noRoomMessage(self):
        dicNoRoomMessage = OrderedDict()
        dicNoRoomMessage[KEY_MESSAGE_TYPE] = MessageType.ERROR_NO_ROOM

        strJsonMessage = json.dumps(dicNoRoomMessage)
        return strJsonMessage

    def returnRoom(self, nRoomID, nPlayerIndex, returnedPlayer):
        try:
            if self.m_dicRoomPlayers.has_key(nRoomID):
                rgPlayers = self.m_dicRoomPlayers[nRoomID]
                player = rgPlayers[nPlayerIndex + 1]
                gameManage = player.m_gameManage
                if (gameManage == False or player.m_bIsAI == False):
                    return (self.__noRoomMessage(), False)
                else:
                    rgPlayers[nPlayerIndex + 1] = returnedPlayer
                    player = None
                    
                    rgCurrentPlayer = []
                    i = 1
                    while i < len(rgPlayers):
                        rgCurrentPlayer.append(rgPlayers[i])
                        i += 1
                    for player in rgCurrentPlayer:
                        player.resetOpponent(rgCurrentPlayer)
                    
                    return (gameManage.getGameContinueMessage(), gameManage)
            else:
                return (self.__noRoomMessage(), False)
        except Exception,e:
            print "error : ", e
            return (self.__noRoomMessage(), False)
# code for AI
    def createSomeRooms(self):
        i = 0
        while i < START_ROOM_COUNT:
            nRoomID = random.randint(1,9) * 1000 + random.randint(0,999)
            j = 0
            while i < 10000 and self.m_dicRoomPlayers.has_key(nRoomID):
                nRoomID = random.randint(1,9) * 1000 + random.randint(0,999)
                j += 1
            
            nPlayerCount = i % 3 + 3
            rgPlayers = []
            rgPlayers.append(nPlayerCount)
            self.m_dicRoomPlayers[nRoomID] = rgPlayers
            self.m_rgWaittingRoom.append(nRoomID)
            print "Create Room %d" % nRoomID
            i += 1
    
    def createSomeAIs(self):
        i = 0
        while i < START_AI_COUNT:
#            AI = AIManage.SimpleAI(self)
            AI = WeightAI.WeightAI(self)
            self.AITryToJoinRoom(AI)
            i += 1

    def kickPlayerOut(self, nPlayerIndex, nRoomID):
        try:
            if self.m_dicRoomPlayers.has_key(nRoomID):
                rgPlayers = self.m_dicRoomPlayers[nRoomID]
                player = rgPlayers[nPlayerIndex + 1]
                self.playerLeftRoom(player, nRoomID)
        except Exception,e:
            print 'error:',e
    
    def playerLeftRoom(self, player, nRoomID):
        try:
            if self.m_dicRoomPlayers.has_key(nRoomID):
                rgPlayers = self.m_dicRoomPlayers[nRoomID]
                nPlayerIndex = player.m_nPlayerIndex
                gameManage = player.m_gameManage
                player.breakConnectionWithOpponent()
                rgPlayers.remove(player)
                print "Player %d left room!" % nPlayerIndex
                
                if player.m_bIsAI == True:
                    self.AITryToJoinRoom(player)
                
                i = 1
                bAllPlayerIsAI = True
                while i < len(rgPlayers):
                    if rgPlayers[i].m_bIsAI == False:
                        bAllPlayerIsAI = False
                        break
                    i += 1
                
                if bAllPlayerIsAI == True:
                    if self.m_rgWaittingRoom.count(nRoomID) > 0:
                        self.m_rgWaittingRoom.remove(nRoomID)

                    while len(rgPlayers) > 1:
                        p = rgPlayers.pop()
                        print "Player %s left room!" % p.m_strPlayerName
                        p.breakConnectionWithOpponent()
                        if p.m_bIsTemp == False:
                            self.AITryToJoinRoom(p)
                        else:
                            p = None
                elif gameManage != False and gameManage.m_bGameOver == False:
                    AI = WeightAI.WeightAI(self)
                    AI.setGameInfo(nRoomID, nPlayerIndex)
                    rgPlayers.append(AI)
                    
                    rgCurrentPlayer = []
                    i = 1
                    while i < len(rgPlayers):
                        rgCurrentPlayer.append(rgPlayers[i])
                        i += 1
                    for player in rgCurrentPlayer:
                        player.resetOpponent(rgCurrentPlayer)
                    AI.midwayStartGame(gameManage)
                
                if len(rgPlayers) == 1:
                    self.m_dicRoomPlayers.pop(nRoomID)
                    if self.m_rgWaittingRoom.count(nRoomID) > 0:
                        self.m_rgWaittingRoom.remove(nRoomID)

        except Exception,e:
            print 'error:',e

    def AITryToJoinRoom(self, AI):
        try:
            rgPlayers = []
            nWaittingRoomIndex = 0
            nRoomID = -1
            while len(self.m_rgWaittingRoom) > nWaittingRoomIndex :
                nRoomID = self.m_rgWaittingRoom[nWaittingRoomIndex]
                nPlayerCount = self.m_dicRoomPlayers[nRoomID][0]
                # When AI is the last Player, check if the room is full of AI
                if nPlayerCount == len(self.m_dicRoomPlayers[nRoomID]):
                    i = 1
                    bAllAI = True
                    while i < len(self.m_dicRoomPlayers[nRoomID]):
                        if self.m_dicRoomPlayers[nRoomID][i].m_bIsAI == False:
                            bAllAI = False
                            break
                        i += 1
                    
                    if bAllAI == False:
                        rgPlayers = self.m_dicRoomPlayers[nRoomID]
                        rgPlayers.append(AI)
                        break
                    else:
                        nWaittingRoomIndex += 1
                        continue
                else:
                    rgPlayers = self.m_dicRoomPlayers[nRoomID]
                    rgPlayers.append(AI)
                    break
        
            # Create New Room
            if len(rgPlayers) == 0:
                i = 0
                nRoomID = random.randint(1,9) * 1000 + random.randint(0,999)
                while i < 10000 and self.m_dicRoomPlayers.has_key(nRoomID):
                    nRoomID = random.randint(1,9) * 1000 + random.randint(0,999)
                    i += 1

                rgPlayers.append(random.randint(3,5))
                rgPlayers.append(AI)
                self.m_dicRoomPlayers[nRoomID] = rgPlayers
                self.m_rgWaittingRoom.append(nRoomID)

                AI.setGameInfo(nRoomID, 0)
                print "AI %s create RoomID %d" % (AI.m_strPlayerName, nRoomID)
            else:
                AI.setGameInfo(nRoomID, len(rgPlayers) - 2)
                print "AI %s join RoomID %d" % (AI.m_strPlayerName, nRoomID)
                if rgPlayers[0] == len(rgPlayers) - 1:
                    self.roomIsFull(nRoomID)
                    i = 1
                    while i < len(rgPlayers):
                        if rgPlayers[i].m_bIsAI == False:
                            rgPlayers[i].firsStartGame(nRoomID)
                            break
                        i += 1
    
        except Exception,e:
            print 'error:',e
